﻿
using System;
using System.IO;

namespace EmperialApps.WeatherSpark.Data {

    /// <summary>Contains information on a tile maintained by the background agent.</summary>
    public partial struct ForecastInfo {

        private const string IdentifierPrefix = "TileId=";


        /// <summary>Gets a value indicating whether the instance has all the information needed to update a tile.</summary>
        public bool HasActiveTile {
            get { return this.Identifier != null; }
        }


        /// <summary>Gets the full identifier text from the specified tile URI.</summary>
        public static string GetIdentifierFromTileUri( string tileUri ) {
            int identifierStart = tileUri.IndexOf( IdentifierPrefix );
            if( identifierStart < 0 )
                return "";

            string identifier = tileUri.Substring( identifierStart, 1 + IdentifierPrefix.Length );
            return identifier;
        }

        /// <summary>Gets the identifier string for the specified tile ID.</summary>
        public static string CreateIdentifier( int tileId ) {
            return tileId == 0
                 ? null
                 : IdentifierPrefix + tileId;
        }

        /// <summary>Gets the tile ID for the specified identifier string.</summary>
        public static bool TryGetTileId( string identifier, out int tileId ) {
            tileId = 0;
            return identifier != null
                && identifier.StartsWith( IdentifierPrefix )
                && int.TryParse( identifier.Substring( IdentifierPrefix.Length ), out tileId );
        }


        /// <summary>Encodes the tile information into a URI-safe data string.</summary>
        public string Encode( ) {
            byte[] data;
            using( var stream = new MemoryStream( ) ) {
                Save( stream, this );
                data = stream.ToArray( );
            }

            string encoded = Convert.ToBase64String( data );
            return Uri.EscapeDataString( encoded );
        }

        /// <summary>Reads tile information from the specified data string.</summary>
        public static ForecastInfo Decode( string encoded ) {
            string escaped = Uri.UnescapeDataString( encoded );
            byte[] data = Convert.FromBase64String( escaped );
            using( var stream = new MemoryStream( data, writable: false ) ) {
                ForecastInfo[] decoded = Load( stream );
                return decoded[0];
            }
        }


        /// <summary>Writes the specified tile information to the specified binary stream.</summary>
        public static void Save( Stream destination, params ForecastInfo[] infos ) {
            var writer = new BinaryWriter( destination );
            writer.Write( (short)infos.Length );

            foreach( ForecastInfo info in infos )
                info.Write( writer );
        }

        /// <summary>Reads tile information from the specified binary stream.</summary>
        public static ForecastInfo[] Load( Stream source ) {
            var reader = new BinaryReader( source );
            short count = reader.ReadInt16( );

            var infos = new ForecastInfo[count];
            for( int i = 0; i < count; ++i )
                infos[i] = ReadForecastInfo( reader );

            return infos;
        }

    }

}
